package com.common.repostitory.impl;

import com.common.repostitory.CommonRepository;
import com.common.repostitory.hibernate.RowMapping;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 文 件 名 称：CommonRepository.
 * 文 件 说 明：
 * 创   建   人：zpen.
 * 创 建 时 间：2018/2/24 17:00.
 */
@Repository("commonRepository")
@Transactional
public class CommonRepositoryImpl implements CommonRepository {

    @Autowired
    private SessionFactory sessionFactory;

    @Autowired
    public JdbcTemplate jdbcTemplate;

    public Session getCurrentSession(){
        return this.sessionFactory.getCurrentSession();
    }


    public <T, PK extends Serializable> T load(Class<T> entityName, PK id) {
        try{
            T t=(T) getCurrentSession().load(entityName,id);
            if(t!=null){
                flush();
            }
            return t;
        }catch (RuntimeException e){
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public <T> List<T> loadAll(Class<T> entityName) {
        Criteria criteria = getCurrentSession().createCriteria(entityName);
        if(criteria!=null){
            flush();
        }
        return criteria.list();
    }

    public  <T> T getEntity(Class<T> entityName, Serializable id) {
        T t = (T) getCurrentSession().get(entityName,id);
        if(t!=null){
            flush();
        }
        return t;
    }

    public List fillAll() {
        return null;
    }

    public <T> void persist(T entity) {
        try {
            getCurrentSession().persist(entity);
            flush();
        }catch (RuntimeException e){
           e.printStackTrace();
            throw e;
        }

    }

    public <T, PK extends Serializable> PK save(T entity) {
        try {
            PK id = (PK) getCurrentSession().save(entity);
            flush();
            return id;
        }catch (Exception e){
            System.out.println("保存实体失败！"+e.toString());
            throw e;
        }
    }

    public <T> void saveOrUpdate(T entity) {
        try {
            getCurrentSession().saveOrUpdate(entity);
            flush();
        }catch (RuntimeException e){
            e.printStackTrace();
            throw e;
        }

    }

    @Override
    public <T> void update(T entity) {
        try {
            getCurrentSession().update(entity);
            flush();
        }catch (RuntimeException e){
             e.printStackTrace();
            throw e;
        }
    }

    public <T, PK extends Serializable> void deleteById(Class<T> entityName,PK id) {
        Class objectClass = (Class) load(entityName,id);
        getCurrentSession().delete(objectClass);
        flush();
    }
    public <T> void delete(T entity) {
        getCurrentSession().delete(entity);
        flush();
    }

    @Override
    public <T> void batchDelete(Collection<T> entitys) {
        for( T entity:entitys){
          delete(entity);
        }
    }

    @Override
    public <T, PK extends Serializable> void batchDeleteByIds(Class<T> entityName, PK[] ids) {
        for(PK id:ids){
            deleteById(entityName,id);
        }
    }

    public void executeSql(String sql, Object[] param) {
        jdbcTemplate.execute(sql);
    }

    public List<Map<String, Object>> findSql(String sql) {
        return jdbcTemplate.queryForList(sql);
    }

    public List<Map<String, Object>> findSql(String sql, Object[] obj) {
        return jdbcTemplate.queryForList(sql,obj);
    }

    @Override
    public Map<String, Object> getMapSql(String sql, Object[] objs) {
       try {
           RowMapper rowMapper = null;
           rowMapper = RowMapping.getInstance();
           return (Map<String, Object>) this.jdbcTemplate.queryForObject(sql,objs,rowMapper);
       }catch (EmptyResultDataAccessException e){
           return null;
       }
    }

    @Override
    public Integer queryForObject(String sql, Object[] objs) {
        return jdbcTemplate.queryForObject(sql,objs,Integer.class);
    }

    public void flush() {
        getCurrentSession().flush();
    }

    public void clear() {
        getCurrentSession().clear();
    }

    public <T>T getEntityByProperty(Class<T> entityClass, String propertyName, Object value) {
        Assert.hasText(propertyName);
        T t = null;
        try{
            t = (T) createCriteria(entityClass, getCurrentSession(),
                    Restrictions.eq(propertyName, value)).uniqueResult();
        }catch (Exception e){
            e.printStackTrace();
        }
        return t;
    }

    private Criteria createCriteria(Class entityClass, Session session,
                                        Criterion... criterions) {
        Criteria criteria = session.createCriteria(entityClass);
        for (Criterion c : criterions) {
            criteria.add(c);
        }
        return criteria;
    }
}
